package com.qfmy.web.app.service.impl.novel;

import com.qfmy.common.Thread.ThreadPoolConfig;
import com.qfmy.common.exception.BaseException;
import com.qfmy.common.login.LoginUser;
import com.qfmy.common.login.LoginUserHolder;
import com.qfmy.common.result.ResultCodeEnum;
import com.qfmy.model.entity.novel.NovelComment;
import com.qfmy.model.entity.novel.NovelCommentLike;
import com.qfmy.web.app.mapper.novel.NovelCommentLikeMapper;
import com.qfmy.web.app.mapper.novel.NovelCommentMapper;
import com.qfmy.web.app.mapper.user.UserMapper;
import com.qfmy.web.app.service.novel.NovelCommentLikeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.CompletableFuture;

/**
 * @author 清风明月
 * @Package com.qfmy.web.app.service.impl.novel
 * @date 2025/10/31
 * @description 评论点赞表
 */
@Slf4j
@Service
public class NovelCommentLikeServiceImpl implements NovelCommentLikeService {

    /**
     * 注入mapper
     */
    @Autowired
    private NovelCommentLikeMapper novelCommentLikeMapper;

    /**
     * 注入评论mapper
     */
    @Autowired
    private NovelCommentMapper novelCommentMapper;

    /**
     * 注入redisTemplate
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 注入用户mapper
     */
    @Autowired
    private UserMapper userMapper;

    /**
     * 添加点赞
     *
     * @param commentId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCommentLike(Integer commentId) {
        // 1. 校验登录状态
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        if (loginUser == null) {
            throw new BaseException(ResultCodeEnum.APP_LOGIN_AUTH);
        }
        Long userId = loginUser.getUserId();

        // 2. 校验评论有效性
        if (!validateCommentExists(commentId)) {
            throw new BaseException(ResultCodeEnum.COMMENT_NOT_EXIST);
        }

        // 3. 校验是否已点赞（防止重复点赞）
        int existingLike = novelCommentLikeMapper.countByCommentAndUser(commentId, userId);
        if (existingLike > 0) {
            //请勿重复点赞
            throw new BaseException(ResultCodeEnum.REPEAT_ADD);
        }
        // 4.判断之前是否取消过点赞
        NovelCommentLike novelCommentLike = novelCommentLikeMapper.getCommentLikeByCommentId(userId,commentId);
        if(novelCommentLike != null)
        {
            //更新点赞状态
            novelCommentLikeMapper.updateLike(commentId, userId);
        }else{
            novelCommentLikeMapper.addCommentLike(commentId, userId);
        }

        // 5.异步更新点赞统计
        CompletableFuture.runAsync(() -> {
            try {
                // 重试机制：最多重试3次
                int retryCount = 0;
                while (retryCount < 3) {
                    try {
                        novelCommentMapper.updateCommentLikeCount(commentId);
                        break;
                    } catch (Exception e) {
                        retryCount++;
                        log.error("第{}次更新评论[{}]点赞数失败", retryCount, commentId, e);
                        if (retryCount >= 3) {
                            //交给mq处理
                        }
                        Thread.sleep(100 * retryCount); // 指数退避等待
                    }
                }
            } catch (Exception e) {
                log.error("更新评论[{}]点赞数异步任务失败", commentId, e);
            }
        }, ThreadPoolConfig.executorService);

        // 6.异步更新用户点赞统计
        CompletableFuture.runAsync(() -> {
            try {
                // 重试机制：最多重试3次
                int retryCount = 0;
                while (retryCount < 3) {
                    try {
                        //根据评论获取评论信息
                        NovelComment novelComment = novelCommentMapper.selectById(commentId);
                        //获取评论的发布用户
                        Long commentUserId = novelComment.getUserId();
                        userMapper.updateLikeAdd(commentUserId);
                        break;
                    } catch (Exception e) {
                        retryCount++;
                        log.error("第{}次更新评论[{}]点赞数失败", retryCount, commentId, e);
                        if (retryCount >= 3) {
                            //交给mq处理
                        }
                        Thread.sleep(100 * retryCount); // 指数退避等待
                    }
                }
            } catch (Exception e) {
                log.error("更新评论[{}]点赞数异步任务失败", commentId, e);
            }
        }, ThreadPoolConfig.executorService);
    }


    /**
     * 取消点赞
     * @param commentId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelCommentLike(Integer commentId) {
        // 1. 校验登录状态
        LoginUser loginUser = LoginUserHolder.getLoginUser();
        if (loginUser == null) {
            throw new BaseException(ResultCodeEnum.TOKEN_EXPIRED);
        }
        Long userId = loginUser.getUserId();

        // 2. 校验评论有效性
        if (!validateCommentExists(commentId)) {
            throw new BaseException(ResultCodeEnum.COMMENT_NOT_EXIST);
        }

        // 3. 校验是否已取消点赞
        Integer existingLike = novelCommentLikeMapper.isCancel(commentId, userId);
        if (existingLike > 0) {
            //请勿重复取消点赞
            throw new BaseException(ResultCodeEnum.REPEAT_CANCEL);
        }

        // 4. 取消点赞
        novelCommentLikeMapper.cancelCommentLike(commentId, userId);

        // 5.异步更新点赞统计
        CompletableFuture.runAsync(() -> {
            try {
                // 重试机制：最多重试3次
                int retryCount = 0;
                while (retryCount < 3) {
                    try {
                        novelCommentMapper.updateCommentLikeCountRec(commentId);
                        break;
                    } catch (Exception e) {
                        retryCount++;
                        log.error("第{}次更新评论[{}]点赞数失败", retryCount, commentId, e);
                        if (retryCount >= 3) {
                            //交给mq处理
                        }
                        Thread.sleep(100 * retryCount); // 指数退避等待
                    }
                }
            } catch (Exception e) {
                log.error("更新评论[{}]点赞数异步任务失败", commentId, e);
            }
        }, ThreadPoolConfig.executorService);

        // 6.异步更新用户点赞统计
        CompletableFuture.runAsync(() -> {
            try {
                // 重试机制：最多重试3次
                int retryCount = 0;
                while (retryCount < 3) {
                    try {
                        //根据评论id查询评论信息
                        NovelComment novelComment = novelCommentMapper.selectById(commentId);
                        //获取发布评论的用户id
                        Long publishUserId = novelComment.getUserId();
                        //更新用户点赞数
                        userMapper.updateLikeCountReduce(publishUserId);
                        break;
                    } catch (Exception e) {
                        retryCount++;
                        log.error("第{}次更新评论[{}]点赞数失败", retryCount, commentId, e);
                        if (retryCount >= 3) {
                            //交给mq处理
                        }
                        Thread.sleep(100 * retryCount); // 指数退避等待
                    }
                }
            } catch (Exception e) {
                log.error("更新评论[{}]点赞数异步任务失败", commentId, e);
            }
        }, ThreadPoolConfig.executorService);

    }

    /**
     * 校验评论是否有效
     * @param commentId
     * @return
     */
    private boolean validateCommentExists(Integer commentId) {
        // 验证评论是否存在
        NovelComment novelComment = novelCommentMapper.selectById(commentId);
        if (novelComment != null) {
            return true;
        }
        return false;
    }


}
